package xin.exec.executor.config;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * <pre>
 * 线程池配置类
 * 实现 {@link org.springframework.scheduling.annotation.AsyncConfigurer} ：可以更加细粒度的控制，包含异常处理等
 * </pre>
 *
 * @author lixin_ma@outlook.com
 * @version 1.0
 * @since 2019/8/9
 */
@Slf4j
@Component
public class DefaultExecutorConfigurer implements AsyncConfigurer{
	
	@Autowired
	private ExecutorConfig config;

	@Override
	public Executor getAsyncExecutor() {
		log.info("init Async Executor with :{}",JSONObject.toJSONString(config)) ;
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(config.getCorePoolSize());
		executor.setMaxPoolSize(config.getMaxPoolSize());
		executor.setQueueCapacity(config.getQueueCapacity());
		if(StringUtils.isNotBlank(config.getThreadNamePrefix())){
			executor.setThreadNamePrefix(config.getThreadNamePrefix());
		}else if(StringUtils.isNotBlank(config.getBeanName())){
			executor.setBeanName(config.getBeanName());
		}
		RejectedExecutionHandler rejectedExecutionHandler;
		if(config.getRejectedExecutionHandler() != null){
			try {
				rejectedExecutionHandler = config.getRejectedExecutionHandler().newInstance();
			} catch (Exception e) {
				throw new RuntimeException("初始化线程池失败-无法获取拒绝策略",e);
			}
		}else{
			rejectedExecutionHandler = new ThreadPoolExecutor.CallerRunsPolicy();
		}
		executor.setRejectedExecutionHandler(rejectedExecutionHandler);
		executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
		executor.setWaitForTasksToCompleteOnShutdown(
				config.getWaitForTasksToCompleteOnShutdown() == null
						? Boolean.TRUE
						: config.getWaitForTasksToCompleteOnShutdown());
		if(config.getAwaitTerminationSeconds() != null){
			executor.setAwaitTerminationSeconds(config.getAwaitTerminationSeconds());
		}
		if(StringUtils.isNotBlank(config.getThreadNamePrefix())){
			executor.setThreadNamePrefix(config.getThreadNamePrefix());
		}
		if(config.getAllowCoreThreadTimeOut() != null )
			executor.setAllowCoreThreadTimeOut(config.getAllowCoreThreadTimeOut());
		executor.initialize();
		return executor;
	}
	
	@Override
	public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
		return new MyUncaughtExceptionHandler();
	}
}
